import logging
import cv2
import os
import dlib
from skimage import io
import csv
import numpy as np
import pandas as pd

class Facelibrary():
    # 使用数据和文件的路径定义
    def __init__(self):
        self.path_traindataset = "./dataset/task1/traindataset/"
        self.path_train = "./dataset/train/"
        self.path_featureDB = "./dataset/task1/featureDB/"
        self.path_featureMean ="./dataset/task1/featureMean/"
        self.path_predictor = "./dataset/task1/model/shape_predictor_68_face_landmarks.dat"
        self.path_model = "./dataset/task1/model/dlib_face_recognition_resnet_model_v1.dat" 

    def mkdir(self,path):
        folder = os.path.exists(path)
        if not folder:                   #判断是否存在文件夹,如果不存在则创建为文件夹
            os.makedirs(path)            #makedirs 创建文件时如果路径不存在会创建这个路径
            #print ("---  new folder...  ---")
            #print ("---  OK  ---")
            #print ("---  There is this folder!  ---")

# mkdir("traindataset")
# for i in range(1,21,1):
#   path = "traindataset/"+"ID{}".format(str(i))
#   mkdir(path)    
# # 存储人脸库
# mkdir("featureDB")
# mkdir("featureMean")
    def getframe(self):
        frame_interval = 30  # 截取图片间隔帧的数量
        for i in os.listdir(self.path_train):
            pictures_count = 0  # 截取图片的数量
            for j in os.listdir(self.path_train+str(i)): # 遍历各个ID
                # print("正在处理{}/{}".format(i,j))
                vc = cv2.VideoCapture(self.path_train+str(i)+"/"+str(j))  # 读取视频
                #print(file_path+str(i)+"/"+str(j))
                if vc.isOpened():
                    ret, frame = vc.read()
                else:
                    ret = False
                frame_count = 0 # 帧计数
                # 循环读取帧
                while ret:
                    if frame_count % frame_interval == 0:
                        path_image = self.path_traindataset+str(i)+"/"+"{}.jpg".format(str(pictures_count))
                        cv2.imwrite(path_image, frame)
                        pictures_count += 1
                    ret, frame = vc.read()
                    frame_count += 1
                vc.release()
        # print("finish...")

    # 返回单张图像的 128D 特征
    def return_128d_features(self,path_img):
        # 检测人脸
        detector = dlib.get_frontal_face_detector()
        # 人脸预测器，获得64个关键点
        predictor = dlib.shape_predictor(self.path_predictor)
        # 获得128D的人脸特征描述符
        face_feature_128D = dlib.face_recognition_model_v1(self.path_model) 

        img_rd = io.imread(path_img)
        # 色彩空间转换
        img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)

        faces = detector(img_gray, 1)
        if len(faces) != 0:
            # print("检测到人脸图像:{}".format(path_img))
            shape = predictor(img_gray, faces[0])
            face_descriptor = face_feature_128D.compute_face_descriptor(img_gray, shape)
        else:
            face_descriptor = 0
            # print("there is no face")
        return face_descriptor  


    # 将ID文件夹中照片特征提取出来, 写入 CSV
    def write_into_csv(self,path_faces_personX, path_csv):
    # 返回指定的文件夹的文件列表
        dir_pics = os.listdir(path_faces_personX)
        with open(path_csv, "w", newline="") as csvfile:
            writer = csv.writer(csvfile)
            for i in range(len(dir_pics)):
                # 调用return_128d_features()得到128d特征
                # print("正在读的人脸图像：", path_faces_personX + "/" + dir_pics[i])
                features_128d = self.return_128d_features(path_faces_personX + "/" + dir_pics[i])
                #  print(features_128d)
                # 遇到没有检测出人脸的图片跳过
                if features_128d == 0:
                    i += 1
                else:
                    writer.writerow(features_128d)

        # 对不同的人的特征数据进行取均值并将结果存储到all_featurecsv文件中
    def computeMean(self,path_feature):
        head=[]
        for i in range(128):
            fe="feature_"+str(i+1)
            head.append(fe)
            #需设置表头，当表头缺省时，会将第一行数据当作表头
        rdata = pd.read_csv(path_feature,names=head)
        meanValue=rdata.mean()
        return meanValue
        
    def buildlibrary(self):
        #读取所有的人脸图像的数据，将不同人的数据存在不同的csv文件中，以便取均值进行误差降低
        faces = os.listdir(self.path_traindataset)
        for person in faces:
            #print(path_featureDB+ person + ".csv")
            self.write_into_csv(self.path_traindataset+person, self.path_featureDB+ person+".csv")

        #计算各个特征文件中的均值，并将值存在feature_all文件中
        features = os.listdir(self.path_featureDB)
        with open(self.path_featureMean + "feature_all.csv", "w", newline="") as csvfile:
            writer = csv.writer(csvfile)
            for fea in features:
                meanValue = self.computeMean(self.path_featureDB+fea)
                writer.writerow(meanValue)
        #         print("{}人脸特征已经提取完成".format(fea))
        # print("人脸库建立成功...")


